// Decompiled with JetBrains decompiler
// Type: FibMatrix.Config.ConfigFormatter
// Assembly: FMCommon, Version=1.0.8663.21262, Culture=neutral, PublicKeyToken=null
// MVID: 52773074-FB09-4BA0-8FA9-4782D11D6C17
// Assembly location: /Users/mac/work/RiverGame/com.rivergame.fmframework/Runtime/Plugins/FMCommon.dll

using ICSharpCode.SharpZipLib.GZip;
using LZ4;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;

namespace FibMatrix.Config
{
  public class ConfigFormatter
  {
    public static bool skipIdDuplicated = false;
    public static bool ignoreTypeConvertError = false;
    private static byte[] _cacheBytes = new byte[4];
    public static byte[] _skipBuffer = new byte[1024];
    public const int ID_INDEX = 0;
    public const int SKIP_BUFF_LEN = 1024;

    public static MetaSerializeResult SerializeMeta(
      Stream outStream,
      bool compress,
      Dictionary<string, string[][]> metaSetsRaw,
      Dictionary<string, byte[]> rawBytesMap = null,
      Dictionary<string, Dictionary<string, MetaRawTypeInfo>> metaPropTypeMap = null,
      MetaRawContext lastMetaRawContext = null)
    {
      outStream.SetLength(0L);
      outStream.WriteByte(compress ? (byte) 1 : (byte) 0);
      if (!compress)
        return ConfigFormatter.DoSerializeMeta(outStream, metaSetsRaw, rawBytesMap, metaPropTypeMap, lastMetaRawContext);
      Stream stream = outStream;
      using (outStream = (Stream) new MemoryStream())
      {
        MetaSerializeResult metaSerializeResult = ConfigFormatter.DoSerializeMeta(outStream, metaSetsRaw, rawBytesMap, metaPropTypeMap, lastMetaRawContext);
        using (GZipStream gzipStream = new GZipStream(stream, CompressionLevel.Fastest))
        {
          byte[] array = (outStream as MemoryStream).ToArray();
          stream.Write(ConfigFormatUtil.ConvertToBytes(ConfigFormatter._cacheBytes, array.Length), 0, 4);
          gzipStream.Write(array, 0, array.Length);
        }
        return metaSerializeResult;
      }
    }

    private static MetaSerializeResult DoSerializeMeta(
      Stream outStream,
      Dictionary<string, string[][]> metaSetsRaw,
      Dictionary<string, byte[]> rawBytesMap = null,
      Dictionary<string, Dictionary<string, MetaRawTypeInfo>> metaPropTypeMap = null,
      MetaRawContext lastMetaRawContext = null)
    {
      bool flag1 = lastMetaRawContext != null;
      MetaConstantPool constantPool = new MetaConstantPool();
      constantPool.ReadFrom(lastMetaRawContext);
      Dictionary<string, MetaData> dictionary1 = new Dictionary<string, MetaData>(metaSetsRaw.Count);
      MemoryStream ms = new MemoryStream();
      foreach (KeyValuePair<string, string[][]> keyValuePair in metaSetsRaw)
      {
        Dictionary<string, MetaRawTypeInfo> dictionary2 = (Dictionary<string, MetaRawTypeInfo>) null;
        if (metaPropTypeMap != null && !metaPropTypeMap.TryGetValue(keyValuePair.Key, out dictionary2))
          Console.WriteLine(keyValuePair.Key + " don't in script");
        Console.WriteLine("Serialize Meta " + keyValuePair.Key);
        string[] strArray1 = keyValuePair.Value[0];
        int index1 = -1;
        for (int index2 = 0; index2 < strArray1.Length; ++index2)
        {
          string val = strArray1[index2];
          if (val == "id")
            index1 = index2;
          constantPool.GetStringIndex(val, true, 16777215);
        }
        if (index1 > 0)
        {
          string str1 = strArray1[0];
          strArray1[0] = strArray1[index1];
          strArray1[index1] = str1;
          for (int index2 = 1; index2 < keyValuePair.Value.Length; ++index2)
          {
            string[] strArray2 = keyValuePair.Value[index2];
            string str2 = strArray2[0];
            strArray2[0] = strArray2[index1];
            strArray2[index1] = str2;
          }
        }
        MetaData metaData = new MetaData();
        metaData.metaName = keyValuePair.Key;
        if (index1 < 0 & flag1)
          return MetaSerializeResult.CantPatch;
        int length1 = strArray1.Length;
        metaData.propNames = new int[length1];
        metaData.propNamesRaw = new string[length1];
        MetaRawTypeInfo[] metaRawTypeInfoArray = new MetaRawTypeInfo[length1];
        metaData.propTypes = new MetaSerializeType[length1];
        MetaRowData[] metaRowDataArray = metaData.rows = new MetaRowData[keyValuePair.Value.Length - 1];
        dictionary1.Add(keyValuePair.Key, metaData);
        MetaIdType metaIdType = MetaIdType.None;
        for (int col = 0; col < length1; ++col)
        {
          string key = strArray1[col];
          MetaRawTypeInfo valueRawType;
          if (dictionary2 == null || !dictionary2.TryGetValue(key, out valueRawType))
            valueRawType = ConfigFormatter.DetermineValueRawType(keyValuePair.Value, col);
          metaRawTypeInfoArray[col] = valueRawType;
          MetaSerializeType serializeType = ConfigFormatter.ConvertRawTypeToSerializeType(valueRawType.type);
          metaData.propTypes[col] = serializeType;
          if (index1 == col)
          {
            switch (serializeType)
            {
              case MetaSerializeType.Int:
                metaIdType = MetaIdType.Int;
                continue;
              case MetaSerializeType.Long:
                metaIdType = MetaIdType.Long;
                continue;
              case MetaSerializeType.String:
                metaIdType = MetaIdType.String;
                continue;
              default:
                throw new Exception("不支持的id类型:" + serializeType.ToString());
            }
          }
        }
        metaData.idType = metaIdType;
        for (int index2 = 1; index2 < keyValuePair.Value.Length; ++index2)
        {
          int length2 = keyValuePair.Value[index2].Length;
          MetaRowData metaRowData = metaRowDataArray[index2 - 1] = new MetaRowData();
          metaRowData.indexList = new List<int>();
          metaRowData.indexBytesNum = new List<byte>();
          ms.Position = 0L;
          ms.SetLength(0L);
          for (int index3 = 0; index3 < length2; ++index3)
          {
            string strVal = keyValuePair.Value[index2][index3];
            if (index3 == 0)
              metaRowData.id = strVal;
            MetaRawTypeInfo metaRawTypeInfo = metaRawTypeInfoArray[index3];
            MetaRawType metaRawType = strVal != null ? metaRawTypeInfo.type : MetaRawType.Null;
            int num1 = 0;
            byte num2 = 0;
            switch (metaRawType)
            {
              case MetaRawType.Null:
                num2 = ConfigFormatter.SerializeNull(out num1);
                break;
              case MetaRawType.Int:
                num2 = ConfigFormatter.SerializeInt(constantPool, strVal, out num1, index3 == 0);
                break;
              case MetaRawType.Float:
                num2 = ConfigFormatter.SerializeFloat(constantPool, strVal, out num1);
                break;
              case MetaRawType.Long:
                num2 = ConfigFormatter.SerializeLong(constantPool, strVal, out num1, false);
                break;
              case MetaRawType.Double:
                num2 = ConfigFormatter.SerializeDouble(constantPool, strVal, out num1);
                break;
              case MetaRawType.String:
                num2 = ConfigFormatter.SerializeString(constantPool, strVal, out num1);
                break;
              case MetaRawType.IntArray:
                num2 = ConfigFormatter.SerializIntArray(constantPool, ms, strVal, metaRawTypeInfo.context?.ToCharArray(), out num1);
                break;
              case MetaRawType.FloatArray:
                num2 = ConfigFormatter.SerializeFloatArray(constantPool, ms, strVal, metaRawTypeInfo.context?.ToCharArray(), out num1);
                break;
              case MetaRawType.StringArray:
                num2 = ConfigFormatter.SerializeStringArray(constantPool, ms, strVal, metaRawTypeInfo.context?.ToCharArray(), out num1);
                break;
            }
            metaRowData.indexList.Add(num1);
            metaRowData.indexBytesNum.Add(num2);
          }
          metaRowData.extraDataList = ms.Length > 0L ? ms.ToArray() : (byte[]) null;
        }
        for (int index2 = 0; index2 < strArray1.Length; ++index2)
        {
          string val = strArray1[index2];
          metaData.propNames[index2] = constantPool.GetStringIndex(val, false, 16777215);
          metaData.propNamesRaw[index2] = val;
        }
      }
      byte[] buffer = (byte[]) null;
      bool flag2 = false;
      using (MemoryStream memoryStream = new MemoryStream())
      {
        using (BinaryWriter writer = new BinaryWriter((Stream) memoryStream))
        {
          flag2 = constantPool.WriteTo(writer, lastMetaRawContext);
          writer.Flush();
        }
        buffer = memoryStream.ToArray();
      }
      using (BinaryWriter writer1 = new BinaryWriter(outStream))
      {
        writer1.Write(buffer.Length);
        writer1.Write(buffer);
        long position1 = writer1.BaseStream.Position;
        writer1.Write(dictionary1.Count);
        int num1 = 0;
        foreach (KeyValuePair<string, MetaData> keyValuePair in dictionary1)
        {
          MetaSetStatus metaSetStatus;
          byte[] array;
          using (MemoryStream memoryStream = new MemoryStream())
          {
            using (BinaryWriter writer2 = new BinaryWriter((Stream) memoryStream))
            {
              metaSetStatus = ConfigFormatter.WriteMetaSet(keyValuePair.Value, writer2, lastMetaRawContext?.GetMetaItemSet(keyValuePair.Key, false) as MetaItemSet, lastMetaRawContext != null);
              writer2.Flush();
              memoryStream.Flush();
              array = memoryStream.ToArray();
            }
          }
          if (metaSetStatus != MetaSetStatus.NoChange)
          {
            writer1.Write(keyValuePair.Key);
            ++num1;
            ConfigFormatter.WriteByteBlock(writer1, array, metaSetStatus == MetaSetStatus.FullContent);
          }
        }
        long position2 = writer1.BaseStream.Position;
        writer1.Seek((int) position1, SeekOrigin.Begin);
        writer1.Write(num1);
        writer1.Seek((int) position2, SeekOrigin.Begin);
        int num2 = rawBytesMap != null ? rawBytesMap.Count : 0;
        long position3 = writer1.BaseStream.Position;
        writer1.Write(num2);
        int num3 = 0;
        if (num2 > 0)
        {
          foreach (KeyValuePair<string, byte[]> rawBytes1 in rawBytesMap)
          {
            byte[] rawBytes2 = lastMetaRawContext?.GetRawBytes(rawBytes1.Key);
            if (rawBytes2 == null || !ConfigFormatter.CompareBytes(rawBytes1.Value, 0, rawBytes1.Value.Length, rawBytes2, 0, rawBytes2.Length))
            {
              ++num3;
              writer1.Write(rawBytes1.Key);
              ConfigFormatter.WriteByteBlock(writer1, rawBytes1.Value, true);
            }
          }
        }
        long position4 = writer1.BaseStream.Position;
        writer1.Seek((int) position3, SeekOrigin.Begin);
        writer1.Write(num3);
        writer1.Seek((int) position4, SeekOrigin.Begin);
        writer1.Flush();
        if (!flag2)
        {
          if (num1 == 0)
          {
            if (num3 == 0)
              return MetaSerializeResult.NoDiff;
          }
        }
      }
      return MetaSerializeResult.Normal;
    }

    private static void WriteByteBlock(BinaryWriter writer, byte[] bytes, bool fullContent)
    {
      MetaFlags metaFlags = fullContent ? MetaFlags.FullContent : MetaFlags.None;
      writer.Write((byte) metaFlags);
      writer.Write(ConfigFormatUtil.ConvertToBytes(ConfigFormatter._cacheBytes, bytes.Length), 0, 4);
      writer.Write(bytes);
    }

    private static byte GetIndexByteNum(int index)
    {
      if ((uint) index <= (uint) byte.MaxValue)
        return 1;
      if ((uint) index <= (uint) ushort.MaxValue)
        return 2;
      return (uint) index <= 16777215U ? (byte) 3 : (byte) 4;
    }

    private static byte GetIntByteNum(int index)
    {
      if ((uint) index <= (uint) byte.MaxValue)
        return 1;
      return (uint) index <= (uint) ushort.MaxValue ? (byte) 2 : (byte) 4;
    }

    private static byte SerializeNull(out int indexOrVal)
    {
      indexOrVal = -1;
      return 0;
    }

    private static byte SerializeString(
      MetaConstantPool constantPool,
      string strVal,
      out int index)
    {
      index = constantPool.GetStringIndex(strVal, true, 16777215);
      if (index < 0)
        throw new Exception("String pool exceed max limit");
      return ConfigFormatter.GetIndexByteNum(index);
    }

    private static byte SerializeDouble(
      MetaConstantPool constantPool,
      string strVal,
      out int index)
    {
      double val = double.Parse(strVal);
      index = constantPool.GetDoubleIndex(val, true, 16777215);
      if (index < 0)
        throw new Exception("Double pool exceed max limit");
      return ConfigFormatter.GetIndexByteNum(index);
    }

    private static byte SerializeLong(
      MetaConstantPool constantPool,
      string strVal,
      out int index,
      bool isId = false)
    {
      long result1;
      if (!long.TryParse(strVal, out result1))
      {
        if (isId)
          throw new Exception("无法将id " + strVal + " 转换为long类型");
        double result2;
        if (double.TryParse(strVal, out result2))
        {
          result1 = (long) result2;
          Console.WriteLine("警告: " + strVal + "无法转为long, 会自动尝试转为double, double值为 " + result2.ToString() + " 转换完的long值为 " + result1.ToString());
        }
        else
          Console.WriteLine("警告: " + strVal + "既无法转为long也无法转为double");
      }
      index = constantPool.GetLongIndex(result1, true, 16777215);
      if (index < 0)
        throw new Exception("Long pool exceed max limit");
      return ConfigFormatter.GetIndexByteNum(index);
    }

    private static byte SerializeInt(
      MetaConstantPool constantPool,
      string strVal,
      out int intVal,
      bool isId = false)
    {
      if (!int.TryParse(strVal, out intVal))
      {
        if (isId)
          throw new Exception("无法将id " + strVal + " 转换为int类型");
        float result;
        if (float.TryParse(strVal, out result))
        {
          intVal = (int) result;
          Console.WriteLine("警告: " + strVal + "无法转为int, 已自动尝试转为float, float值为 " + result.ToString() + " 转换完的int值为 " + intVal.ToString());
        }
        else
        {
          intVal = 0;
          Console.WriteLine("警告: " + strVal + "既无法转为int也无法转为float");
        }
      }
      return ConfigFormatter.GetIntByteNum(intVal);
    }

    private static byte SerializeFloat(MetaConstantPool constantPool, string strVal, out int index)
    {
      float val = float.Parse(strVal);
      index = constantPool.GetFloatIndex(val, true, 16777215);
      if (index < 0)
        throw new Exception("Float pool exceed max limit");
      return ConfigFormatter.GetIndexByteNum(index);
    }

    private static byte SerializIntArray(
      MetaConstantPool constantPool,
      MemoryStream ms,
      string strVal,
      char[] separator,
      out int indexOrVal)
    {
      string[] strArray = strVal.Split(separator);
      int length = strArray.Length;
      if (length <= 0)
        return ConfigFormatter.SerializeNull(out indexOrVal);
      int position1 = (int) ms.Position;
      ConfigFormatUtil.Write7BitEncodedInt(ms, length);
      if (length >= 4)
      {
        int position2 = (int) ms.Position;
        byte[] buffer = new byte[length % 4 == 0 ? length / 4 : length / 4 + 1];
        ms.Write(buffer, 0, buffer.Length);
        for (int index = 0; index < length; ++index)
        {
          int intVal;
          byte num = ConfigFormatter.SerializeInt(constantPool, strArray[index], out intVal, false);
          ConfigFormatUtil.Write(ms, intVal, num);
          buffer[index / 4] |= (byte) ((uint) ConfigFormatUtil.EncodeIntByteLen(num) << (index % 4 << 1));
        }
        int position3 = (int) ms.Position;
        ms.Position = (long) position2;
        ms.Write(buffer, 0, buffer.Length);
        ms.Position = (long) position3;
      }
      else
      {
        for (int index = 0; index < length; ++index)
        {
          int intVal;
          int num = (int) ConfigFormatter.SerializeInt(constantPool, strArray[index], out intVal, false);
          ConfigFormatUtil.Write7BitEncodedInt(ms, intVal);
        }
      }
      indexOrVal = position1;
      return ConfigFormatter.GetIntByteNum(position1);
    }

    private static byte SerializeFloatArray(
      MetaConstantPool constantPool,
      MemoryStream ms,
      string strVal,
      char[] separator,
      out int indexOrVal)
    {
      string[] strArray = strVal.Split(separator);
      int length = strArray.Length;
      if (length <= 0)
        return ConfigFormatter.SerializeNull(out indexOrVal);
      int position1 = (int) ms.Position;
      ConfigFormatUtil.Write7BitEncodedInt(ms, length);
      if (length >= 4)
      {
        int position2 = (int) ms.Position;
        byte[] buffer = new byte[length % 4 == 0 ? length / 4 : length / 4 + 1];
        ms.Write(buffer, 0, buffer.Length);
        for (int index1 = 0; index1 < length; ++index1)
        {
          int index2;
          byte num = ConfigFormatter.SerializeFloat(constantPool, strArray[index1], out index2);
          ConfigFormatUtil.Write(ms, index2, num);
          buffer[index1 / 4] |= (byte) ((uint) ConfigFormatUtil.EncodeOtherByteLen(num) << (index1 % 4 << 1));
        }
        int position3 = (int) ms.Position;
        ms.Position = (long) position2;
        ms.Write(buffer, 0, buffer.Length);
        ms.Position = (long) position3;
      }
      else
      {
        for (int index1 = 0; index1 < length; ++index1)
        {
          int index2;
          int num = (int) ConfigFormatter.SerializeFloat(constantPool, strArray[index1], out index2);
          ConfigFormatUtil.Write7BitEncodedInt(ms, index2);
        }
      }
      indexOrVal = position1;
      return ConfigFormatter.GetIntByteNum(position1);
    }

    private static byte SerializeStringArray(
      MetaConstantPool constantPool,
      MemoryStream ms,
      string strVal,
      char[] separator,
      out int indexOrVal)
    {
      string[] strArray = strVal.Split(separator);
      int length = strArray.Length;
      if (length <= 0)
        return ConfigFormatter.SerializeNull(out indexOrVal);
      int position1 = (int) ms.Position;
      ConfigFormatUtil.Write7BitEncodedInt(ms, length);
      if (length >= 4)
      {
        int position2 = (int) ms.Position;
        byte[] buffer = new byte[length % 4 == 0 ? length / 4 : length / 4 + 1];
        ms.Write(buffer, 0, buffer.Length);
        for (int index1 = 0; index1 < length; ++index1)
        {
          int index2;
          byte num = ConfigFormatter.SerializeString(constantPool, strArray[index1], out index2);
          ConfigFormatUtil.Write(ms, index2, num);
          buffer[index1 / 4] |= (byte) ((uint) ConfigFormatUtil.EncodeOtherByteLen(num) << (index1 % 4 << 1));
        }
        int position3 = (int) ms.Position;
        ms.Position = (long) position2;
        ms.Write(buffer, 0, buffer.Length);
        ms.Position = (long) position3;
      }
      else
      {
        for (int index1 = 0; index1 < length; ++index1)
        {
          int index2;
          int num = (int) ConfigFormatter.SerializeString(constantPool, strArray[index1], out index2);
          ConfigFormatUtil.Write7BitEncodedInt(ms, index2);
        }
      }
      indexOrVal = position1;
      return ConfigFormatter.GetIntByteNum(position1);
    }

    private static MetaSerializeType ConvertRawTypeToSerializeType(
      MetaRawType rawType)
    {
      switch (rawType)
      {
        case MetaRawType.Null:
          return MetaSerializeType.Null;
        case MetaRawType.Int:
          return MetaSerializeType.Int;
        case MetaRawType.Float:
          return MetaSerializeType.Float;
        case MetaRawType.Long:
          return MetaSerializeType.Long;
        case MetaRawType.Double:
          return MetaSerializeType.Double;
        case MetaRawType.String:
          return MetaSerializeType.String;
        case MetaRawType.IntArray:
          return MetaSerializeType.IntArray;
        case MetaRawType.FloatArray:
          return MetaSerializeType.FloatArray;
        case MetaRawType.StringArray:
          return MetaSerializeType.StringArray;
        default:
          throw new Exception("Unsupported rawType " + rawType.ToString());
      }
    }

    private static MetaRawTypeInfo DetermineValueRawType(string[][] rowArr, int col)
    {
      MetaRawType type = MetaRawType.Null;
      for (int index = 1; index < rowArr.Length; ++index)
      {
        string[] strArray = rowArr[index];
        if (strArray != null && col < strArray.Length)
        {
          MetaRawType metaRawType = ConfigFormatter.CheckType(strArray[col]);
          if (metaRawType > type)
            type = metaRawType;
        }
      }
      return new MetaRawTypeInfo(type, (string) null);
    }

    private static MetaRawType CheckType(string val)
    {
      int result1;
      if (int.TryParse(val, out result1) && result1.ToString() == val)
        return MetaRawType.Int;
      long result2;
      if (long.TryParse(val, out result2) && result2.ToString() == val)
        return MetaRawType.Long;
      float result3;
      if (float.TryParse(val, out result3) && result3.ToString() == val)
        return MetaRawType.Float;
      double result4;
      return double.TryParse(val, out result4) && result4.ToString() == val ? MetaRawType.Double : MetaRawType.String;
    }

    private static MetaSetStatus WriteMetaSet(
      MetaData set,
      BinaryWriter writer,
      MetaItemSet lastMetaSet,
      bool logFullContentPatch)
    {
      MetaSetStatus metaSetStatus = MetaSetStatus.NoChange;
      byte[] buffer1 = new byte[4];
      if (lastMetaSet != null)
      {
        if (lastMetaSet.idType == set.idType && lastMetaSet.propNum == set.propNames.Length && set.idType != MetaIdType.None)
        {
          for (int index = 0; index < set.propNames.Length; ++index)
          {
            string propName = set.propNamesRaw[index];
            int id;
            if (!lastMetaSet.TryGetPropNameId(propName, out id) || id != index)
            {
              if (logFullContentPatch)
                Console.WriteLine(set.metaName + " patch full content, last index: " + id.ToString() + " index: " + index.ToString());
              lastMetaSet = (MetaItemSet) null;
              break;
            }
          }
          if (lastMetaSet != null)
          {
            Dictionary<string, MetaSerializeType> propertyNameAndType = lastMetaSet.GetAllPropertyNameAndType();
            MetaSerializeType[] propTypes = set.propTypes;
            for (int index = 0; index < set.propNames.Length; ++index)
            {
              string key = set.propNamesRaw[index];
              MetaSerializeType metaSerializeType1 = propTypes[index];
              MetaSerializeType metaSerializeType2;
              if (!propertyNameAndType.TryGetValue(key, out metaSerializeType2) || metaSerializeType2 != metaSerializeType1)
              {
                if (logFullContentPatch)
                  Console.WriteLine(set.metaName + " patch full content, prop: " + key + " last type: " + metaSerializeType2.ToString() + " cur type: " + metaSerializeType1.ToString());
                lastMetaSet = (MetaItemSet) null;
                break;
              }
            }
          }
        }
        else
        {
          if (logFullContentPatch)
            Console.WriteLine(set.metaName + " patch full content, no id or propNum changed");
          lastMetaSet = (MetaItemSet) null;
        }
      }
      else if (logFullContentPatch)
        Console.WriteLine(set.metaName + " patch full content, no last meta");
      if (lastMetaSet == null)
        metaSetStatus = MetaSetStatus.FullContent;
      int length = set.propNames.Length;
      long position1;
      if (metaSetStatus == MetaSetStatus.FullContent)
      {
        writer.Write((byte) set.idType);
        position1 = writer.BaseStream.Position;
        writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, set.rows.Length), 0, 4);
        writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, length), 0, 4);
        foreach (int propName in set.propNames)
          writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, propName), 0, 4);
        byte[] buffer2 = new byte[length % 2 == 0 ? length / 2 : length / 2 + 1];
        for (int index = 0; index < length; ++index)
          buffer2[index / 2] |= (byte) ((uint) set.propTypes[index] << index % 2 * 4);
        writer.Write(buffer2);
      }
      else
      {
        writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, set.rows.Length), 0, 4);
        writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, lastMetaSet.propRowPosStartOffset), 0, 4);
        writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, lastMetaSet.propRowAreaStartOffset), 0, 4);
        writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, lastMetaSet.propAreaLength), 0, 4);
        position1 = writer.BaseStream.Position;
        writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, set.rows.Length), 0, 4);
      }
      Dictionary<string, (long, long)> dictionary = new Dictionary<string, (long, long)>();
      List<string> stringList = new List<string>();
      using (MemoryStream memoryStream = new MemoryStream())
      {
        using (BinaryWriter writer1 = new BinaryWriter((Stream) memoryStream))
        {
          int num1 = 0;
          foreach (MetaRowData row in set.rows)
          {
            long position2 = writer1.BaseStream.Position;
            int count = row.indexBytesNum.Count;
            if (count > length)
              throw new Exception("typeList length incorrect");
            ConfigFormatUtil.Write7BitEncodedInt(writer1, count);
            byte[] buffer2 = new byte[count % 4 == 0 ? count / 4 : count / 4 + 1];
            for (int index = 0; index < count; ++index)
            {
              switch (set.propTypes[index])
              {
                case MetaSerializeType.Int:
                case MetaSerializeType.IntArray:
                case MetaSerializeType.FloatArray:
                case MetaSerializeType.StringArray:
                  buffer2[index / 4] |= (byte) ((uint) ConfigFormatUtil.EncodeIntByteLen(row.indexBytesNum[index]) << (index % 4 << 1));
                  break;
                default:
                  buffer2[index / 4] |= (byte) ((uint) ConfigFormatUtil.EncodeOtherByteLen(row.indexBytesNum[index]) << (index % 4 << 1));
                  break;
              }
            }
            writer1.Write(buffer2);
            ++num1;
            for (int index1 = 0; index1 < count; ++index1)
            {
              int index2 = row.indexList[index1];
              byte byteNum = row.indexBytesNum[index1];
              if (byteNum > (byte) 0)
                writer1.Write(ConfigFormatUtil.ConvertToBytes(buffer1, index2, byteNum), 0, (int) byteNum);
            }
            if (row.extraDataList != null)
            {
              ConfigFormatUtil.Write7BitEncodedInt(writer1, row.extraDataList.Length);
              writer1.Write(row.extraDataList);
            }
            else
              ConfigFormatUtil.Write7BitEncodedInt(writer1, 0);
            long position3 = writer1.BaseStream.Position;
            if (row.id != null && dictionary.ContainsKey(row.id))
            {
              if (ConfigFormatter.skipIdDuplicated)
              {
                stringList.Add(row.id);
                dictionary[row.id] = (position2, position3 - position2);
                Console.WriteLine("Sheet " + set.metaName + " id " + row.id + " 重复");
              }
              else
                throw new Exception("Sheet " + set.metaName + " id " + row.id + " 重复");
            }
            else
            {
              string key = row.id == null ? (num1 - 1).ToString() : row.id;
              stringList.Add(key);
              dictionary.Add(key, (position2, position3 - position2));
            }
          }
          byte[] array = memoryStream.ToArray();
          if (metaSetStatus != MetaSetStatus.FullContent)
          {
            List<string> ids;
            Dictionary<string, (int, int)> rowPosAndLengthMap = lastMetaSet.CalculateRowPosAndLengthMap(out ids);
            HashSet<string> stringSet1 = new HashSet<string>();
            HashSet<string> stringSet2 = new HashSet<string>();
            List<int> intList = new List<int>();
            foreach (string key in stringList)
            {
              if (!rowPosAndLengthMap.ContainsKey(key))
                stringSet1.Add(key);
              else if (!ConfigFormatter.CompareBytes(array, (int) dictionary[key].Item1, (int) dictionary[key].Item2, lastMetaSet.buffer, rowPosAndLengthMap[key].Item1, rowPosAndLengthMap[key].Item2))
              {
                stringSet2.Add(key);
                stringSet1.Add(key);
              }
            }
            for (int index = 0; index < ids.Count; ++index)
            {
              if (!dictionary.ContainsKey(ids[index]))
                intList.Add(index);
            }
            if (stringSet1.Count <= 0)
            {
              if (intList.Count <= 0)
                goto label_111;
            }
            metaSetStatus = MetaSetStatus.PartialPatch;
            string[] strArray = new string[7];
            strArray[0] = set.metaName;
            strArray[1] = " modifyOrAdd count ";
            int count = stringSet1.Count;
            strArray[2] = count.ToString();
            strArray[3] = ", modify count ";
            count = stringSet2.Count;
            strArray[4] = count.ToString();
            strArray[5] = ", delete Count ";
            count = intList.Count;
            strArray[6] = count.ToString();
            Console.WriteLine(string.Concat(strArray));
            int num2 = Math.Max(ids.Count, stringList.Count);
            int num3 = 0;
            int num4 = -1;
            for (int index = 0; index < num2; ++index)
            {
              if (index >= ids.Count || index >= stringList.Count || (ids[index] != stringList[index] || stringSet2.Contains(ids[index])))
              {
                num4 = index;
                break;
              }
              ++num3;
            }
            int num5 = 0;
            int num6 = -1;
            int index1 = ids.Count - 1;
            int index2;
            for (index2 = stringList.Count - 1; index1 >= 0 && index2 >= 0; --index2)
            {
              if (ids[index1] != stringList[index2] || stringSet2.Contains(ids[index1]))
              {
                num6 = index2;
                break;
              }
              ++num5;
              --index1;
            }
            if (index2 >= 0 && num6 < 0)
              num6 = index2;
            ConfigFormatUtil.Write7BitEncodedInt(writer, num3);
            ConfigFormatUtil.Write7BitEncodedInt(writer, num5);
            int num7 = 0;
            for (int index3 = num4; index3 <= num6; ++index3)
            {
              if (stringSet1.Contains(stringList[index3]))
              {
                writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, num7 + lastMetaSet.propAreaLength), 0, 4);
                num7 += (int) dictionary[stringList[index3]].Item2;
              }
              else
                writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, rowPosAndLengthMap[stringList[index3]].Item1 - lastMetaSet.propRowAreaStartOffset), 0, 4);
            }
            for (int index3 = num4; index3 <= num6; ++index3)
            {
              if (stringSet1.Contains(stringList[index3]))
                writer.Write(array, (int) dictionary[stringList[index3]].Item1, (int) dictionary[stringList[index3]].Item2);
            }
            long position2 = writer.BaseStream.Position;
            writer.Seek((int) position1, SeekOrigin.Begin);
            writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, num4 <= num6 ? num6 - num4 + 1 : 0), 0, 4);
            writer.Seek((int) position2, SeekOrigin.Begin);
          }
          else
          {
            foreach (string index in stringList)
              writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, (int) dictionary[index].Item1), 0, 4);
            writer.Write(ConfigFormatUtil.ConvertToBytes(buffer1, array.Length), 0, 4);
            writer.Write(array);
          }
        }
      }
label_111:
      return metaSetStatus;
    }

    private static unsafe bool CompareBytes(
      byte[] srcBytes,
      int srcOffset,
      int srcLength,
      byte[] dstBytes,
      int dstOffset,
      int dstLength)
    {
      if (srcLength != dstLength)
        return false;
      fixed (byte* numPtr1 = &srcBytes[srcOffset])
        fixed (byte* numPtr2 = &dstBytes[dstOffset])
        {
          for (int index = 0; index < srcLength; ++index)
          {
            if ((int) numPtr1[index] != (int) numPtr2[index])
              return false;
          }
        }
      return true;
    }

    public static void SerializeLocale(Stream outStream, Dictionary<string, string> languageMap)
    {
      outStream.SetLength(0L);
      using (LZ4Stream lz4Stream = new LZ4Stream(outStream, LZ4StreamMode.Compress, LZ4StreamFlags.None, 65536))
      {
        using (BinaryWriter writer = new BinaryWriter((Stream) lz4Stream))
        {
          ConfigFormatter.WriteDict(languageMap, writer);
          writer.Flush();
          lz4Stream.Flush();
        }
      }
    }

    private static void WriteDict(Dictionary<string, string> dict, BinaryWriter writer)
    {
      writer.Write(dict.Count);
      foreach (KeyValuePair<string, string> keyValuePair in dict)
      {
        writer.Write(keyValuePair.Key);
        writer.Write(keyValuePair.Value);
      }
    }

    private static void ReadByteBlock(
      BinaryReader reader,
      HashSet<string> allBlockNames,
      Dictionary<string, MetaPosStatus> posMap,
      int offset,
      byte[] src)
    {
      Stream baseStream = reader.BaseStream;
      string key = reader.ReadString();
      allBlockNames.Add(key);
      int position = (int) baseStream.Position;
      MetaFlags metaFlags = (MetaFlags) reader.ReadByte();
      int num1 = (uint) (metaFlags & MetaFlags.Compressed) > 0U ? 1 : 0;
      reader.Read(ConfigFormatter._cacheBytes, 0, 4);
      int num2 = ConfigFormatUtil.ReadInt32(ConfigFormatter._cacheBytes, 0);
      if (num1 != 0)
        num2 += 4;
      baseStream.Position += (long) num2;
      MetaPosStatus metaPosStatus;
      if (posMap.TryGetValue(key, out metaPosStatus))
      {
        if ((metaFlags & MetaFlags.FullContent) != MetaFlags.None)
        {
          metaPosStatus.pos = position + offset;
          metaPosStatus.src = src;
          metaPosStatus.patchPos = -1;
          metaPosStatus.patchSrc = (byte[]) null;
        }
        else
        {
          metaPosStatus.patchPos = position + offset;
          metaPosStatus.patchSrc = src;
        }
      }
      else
        posMap.Add(key, new MetaPosStatus()
        {
          pos = position + offset,
          src = src,
          patchPos = -1,
          patchSrc = (byte[]) null
        });
    }

    private static byte[] TryDecompress(byte[] src, bool forceUseSystemGZip = false)
    {
      if (src == null)
        return (byte[]) null;
      if (src[0] != (byte) 1)
        return src;
      int count = ConfigFormatUtil.ReadInt32(src, 1);
      byte[] buffer = new byte[count];
      if (IntPtr.Size == 8 | forceUseSystemGZip)
      {
        MemoryStream memoryStream = new MemoryStream(src, 5, src.Length - 5);
        Stopwatch stopwatch = Stopwatch.StartNew();
        GZipStream gzipStream = new GZipStream((Stream) memoryStream, CompressionMode.Decompress);
        gzipStream.Read(buffer, 0, count);
        gzipStream.Dispose();
        stopwatch.Stop();
        memoryStream.Dispose();
      }
      else
      {
        MemoryStream memoryStream = new MemoryStream(src, 5, src.Length - 5);
        Stopwatch stopwatch = Stopwatch.StartNew();
        GZipInputStream gzipInputStream = new GZipInputStream((Stream) memoryStream, 524288);
        gzipInputStream.Read(buffer, 0, count);
        gzipInputStream.Dispose();
        stopwatch.Stop();
        memoryStream.Dispose();
      }
      return buffer;
    }

    public static MetaRawContext DeserializeMeta(
      byte[] src,
      byte[] patchSrc = null,
      bool logPerformanceWarning = true,
      bool forceUseSystemGZip = false)
    {
      string[] uniqueStrs = (string[]) null;
      int[] uniqueInts = (int[]) null;
      long[] uniqueLongs = (long[]) null;
      float[] uniqueFloats = (float[]) null;
      double[] uniqueDoubles = (double[]) null;
      Dictionary<string, MetaPosStatus> dictionary1 = (Dictionary<string, MetaPosStatus>) null;
      Dictionary<string, MetaPosStatus> dictionary2 = (Dictionary<string, MetaPosStatus>) null;
      src = ConfigFormatter.TryDecompress(src, forceUseSystemGZip);
      patchSrc = ConfigFormatter.TryDecompress(patchSrc, forceUseSystemGZip);
      int count1 = ConfigFormatUtil.ReadInt32(src, 0);
      int count2 = patchSrc != null ? ConfigFormatUtil.ReadInt32(patchSrc, 0) : 0;
      using (MemoryStream memoryStream1 = new MemoryStream(src, 4, count1))
      {
        using (BinaryReader binaryReader1 = new BinaryReader((Stream) memoryStream1))
        {
          using (MemoryStream memoryStream2 = patchSrc != null ? new MemoryStream(patchSrc, 4, count2) : (MemoryStream) null)
          {
            using (BinaryReader binaryReader2 = memoryStream2 != null ? new BinaryReader((Stream) memoryStream2) : (BinaryReader) null)
            {
              int num1 = binaryReader1.ReadInt32();
              int num2 = binaryReader2 != null ? binaryReader2.ReadInt32() : 0;
              int length1 = num1 + num2;
              uniqueStrs = new string[length1];
              for (int index = 0; index < num1; ++index)
                uniqueStrs[index] = binaryReader1.ReadString();
              for (int index = num1; index < length1; ++index)
                uniqueStrs[index] = binaryReader2.ReadString();
              int num3 = binaryReader1.ReadInt32();
              int num4 = binaryReader2 != null ? binaryReader2.ReadInt32() : 0;
              int length2 = num3 + num4;
              uniqueInts = new int[length2];
              for (int index = 0; index < num3; ++index)
                uniqueInts[index] = binaryReader1.ReadInt32();
              for (int index = num3; index < length2; ++index)
                uniqueInts[index] = binaryReader2.ReadInt32();
              int num5 = binaryReader1.ReadInt32();
              int num6 = binaryReader2 != null ? binaryReader2.ReadInt32() : 0;
              int length3 = num5 + num6;
              uniqueLongs = new long[length3];
              for (int index = 0; index < num5; ++index)
                uniqueLongs[index] = binaryReader1.ReadInt64();
              for (int index = num5; index < length3; ++index)
                uniqueLongs[index] = binaryReader2.ReadInt64();
              int num7 = binaryReader1.ReadInt32();
              int num8 = binaryReader2 != null ? binaryReader2.ReadInt32() : 0;
              int length4 = num7 + num8;
              uniqueFloats = new float[length4];
              for (int index = 0; index < num7; ++index)
                uniqueFloats[index] = binaryReader1.ReadSingle();
              for (int index = num7; index < length4; ++index)
                uniqueFloats[index] = binaryReader2.ReadSingle();
              int num9 = binaryReader1.ReadInt32();
              int num10 = binaryReader2 != null ? binaryReader2.ReadInt32() : 0;
              int length5 = num9 + num10;
              uniqueDoubles = new double[length5];
              for (int index = 0; index < num9; ++index)
                uniqueDoubles[index] = binaryReader1.ReadDouble();
              for (int index = num9; index < length5; ++index)
                uniqueDoubles[index] = binaryReader2.ReadDouble();
            }
          }
        }
      }
      HashSet<string> allBlockNames1 = new HashSet<string>();
      HashSet<string> allBlockNames2 = new HashSet<string>();
      using (MemoryStream memoryStream = new MemoryStream(src, 4 + count1, src.Length - 4 - count1))
      {
        using (BinaryReader reader = new BinaryReader((Stream) memoryStream))
        {
          int capacity1 = reader.ReadInt32();
          dictionary1 = new Dictionary<string, MetaPosStatus>(capacity1);
          for (int index = 0; index < capacity1; ++index)
            ConfigFormatter.ReadByteBlock(reader, allBlockNames1, dictionary1, 4 + count1, src);
          int capacity2 = reader.ReadInt32();
          dictionary2 = new Dictionary<string, MetaPosStatus>(capacity2);
          for (int index = 0; index < capacity2; ++index)
            ConfigFormatter.ReadByteBlock(reader, allBlockNames2, dictionary2, 4 + count1, src);
        }
      }
      if (patchSrc != null)
      {
        HashSet<string> allBlockNames3 = new HashSet<string>();
        HashSet<string> allBlockNames4 = new HashSet<string>();
        using (MemoryStream memoryStream = new MemoryStream(patchSrc, 4 + count2, patchSrc.Length - 4 - count2))
        {
          using (BinaryReader reader = new BinaryReader((Stream) memoryStream))
          {
            int num1 = reader.ReadInt32();
            for (int index = 0; index < num1; ++index)
              ConfigFormatter.ReadByteBlock(reader, allBlockNames3, dictionary1, 4 + count2, patchSrc);
            int num2 = reader.ReadInt32();
            for (int index = 0; index < num2; ++index)
              ConfigFormatter.ReadByteBlock(reader, allBlockNames4, dictionary2, 4 + count2, patchSrc);
          }
        }
      }
      return new MetaRawContext(uniqueStrs, uniqueInts, uniqueLongs, uniqueFloats, uniqueDoubles, dictionary1, dictionary2, logPerformanceWarning);
    }

    public static bool ValidateMeta(byte[] src)
    {
      bool flag = false;
      try
      {
        src = ConfigFormatter.TryDecompress(src, false);
        int count = ConfigFormatUtil.ReadInt32(src, 0);
        using (MemoryStream memoryStream = new MemoryStream(src, 4, count))
        {
          do
            ;
          while (memoryStream.Read(ConfigFormatter._skipBuffer, 0, 1024) == 1024);
        }
      }
      catch (Exception ex)
      {
        flag = true;
        Console.WriteLine((object) ex);
      }
      return !flag;
    }

    public static bool ValidateLocale(byte[] src)
    {
      bool flag = false;
      try
      {
        using (MemoryStream memoryStream = new MemoryStream(src))
        {
          using (LZ4Stream lz4Stream = new LZ4Stream((Stream) memoryStream, LZ4StreamMode.Decompress, LZ4StreamFlags.None, 1048576))
          {
            do
              ;
            while (lz4Stream.Read(ConfigFormatter._skipBuffer, 0, 1024) == 1024);
          }
        }
      }
      catch (Exception ex)
      {
        flag = true;
        Console.WriteLine((object) ex);
      }
      return !flag;
    }

    private static List<Hashtable> ReadSet(
      BinaryReader reader,
      List<string> uniqueStrings)
    {
      int capacity1 = reader.ReadInt32();
      List<Hashtable> hashtableList = new List<Hashtable>(capacity1);
      for (int index1 = 0; index1 < capacity1; ++index1)
      {
        int capacity2 = reader.ReadInt32();
        Hashtable hashtable = new Hashtable(capacity2);
        for (int index2 = 0; index2 < capacity2; ++index2)
        {
          string uniqueString1 = uniqueStrings[reader.ReadInt32()];
          string uniqueString2 = uniqueStrings[reader.ReadInt32()];
          hashtable.Add((object) uniqueString1, (object) uniqueString2);
        }
        hashtableList.Add(hashtable);
      }
      return hashtableList;
    }

    private static void SkipSet(BinaryReader reader)
    {
      int num = reader.ReadInt32();
      for (int index = 0; index < num; ++index)
        ConfigFormatter.SkipDict(reader);
    }

    public static Dictionary<string, string> DeserializeLocale(byte[] src)
    {
      Dictionary<string, string> dictionary = (Dictionary<string, string>) null;
      try
      {
        using (MemoryStream memoryStream = new MemoryStream(src))
        {
          using (LZ4Stream lz4Stream = new LZ4Stream((Stream) memoryStream, LZ4StreamMode.Decompress, LZ4StreamFlags.None, 1048576))
          {
            using (BinaryReader reader = new BinaryReader((Stream) lz4Stream))
              dictionary = ConfigFormatter.ReadDict(reader);
          }
        }
      }
      catch (Exception ex)
      {
      }
      return dictionary;
    }

    public static void SkipDict(BinaryReader reader)
    {
      int num = reader.ReadInt32();
      reader.BaseStream.Position += (long) (num * 8);
    }

    public static void SkipString(BinaryReader reader)
    {
      int num = ConfigFormatUtil.Read7BitEncodedInt(reader);
      reader.BaseStream.Position += (long) num;
    }

    public static void FakeReadDict(BinaryReader reader)
    {
      int num = reader.ReadInt32();
      for (int index = 0; index < num; ++index)
      {
        ConfigFormatter.FakeReadString(reader);
        ConfigFormatter.FakeReadString(reader);
      }
    }

    public static void FakeReadString(BinaryReader reader)
    {
      int count = ConfigFormatUtil.Read7BitEncodedInt(reader);
      if (count <= 1024)
      {
        reader.Read(ConfigFormatter._skipBuffer, 0, count);
      }
      else
      {
        for (; count >= 0; count -= 1024)
          reader.Read(ConfigFormatter._skipBuffer, 0, count >= 1024 ? 1024 : count);
      }
    }

    private static Dictionary<string, string> ReadDict(BinaryReader reader)
    {
      int capacity = reader.ReadInt32();
      Dictionary<string, string> dictionary = new Dictionary<string, string>(capacity);
      for (int index = 0; index < capacity; ++index)
      {
        string key = reader.ReadString();
        string str = reader.ReadString();
        dictionary.Add(key, str);
      }
      return dictionary;
    }
  }
}
